

import java.awt.*;
import java.awt.image.ColorModel;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import java.awt.Color.*;
import java.awt.color.ColorSpace;


/**
 *
 * @author MDompekidis
 */
public class IO
{

    /**
     * The constructor method
     */
    public IO ()
    {
        
    }
    
//******************************************************************************       
//load method                                                                  *
//******************************************************************************
    /**
     * Loads a file and converts it to Image, can convert image files as (.jpg, .bmp, .gif, .png, .tif)
     * and dicom files compressed or uncompressed.
     * @param filename The file name of the source file
     * @return An Image
     */
    public static void load(String filename)
    {
        int proceedFlag=0;
        BufferedImage img = null;
        String extensionDictionary[] = {"jpg","png","tif","tiff","bmp","BMP","JPG","PNG","TIF","TIFF","gif","GIF"};
        String extensionForLoading = getExtension(filename);
       
        for(int i=0;i<=11;i++)
        {
            if(extensionForLoading.equals(extensionDictionary[i]))
            {
                proceedFlag = 1;
               
                break;
            }
            
            else
            {
                proceedFlag = 2;
            }
        }
        
        if(proceedFlag == 1)
        {
            
            try 
            {
                //READS AN IMAGE FILE AND STORES IT AS BufferedImage
                img = ImageIO.read(new File(filename));
                
            } 
            catch (IOException e) 
            {
                System.out.print("Cannot read file!\n");
                 
            }
        }
        
       /* else if(proceedFlag == 2)
        {
            try
             {
                
                img = DicomIO.Dcm2Bufferedimage(filename);
                
             } 
             catch (IOException e) 
             {
                e.printStackTrace();
             }
          
        }
        */
        
        slidingWindow(img,24,24,24,24);//BufferedImage2Image(img);
        
          
    }
    
//******************************************************************************       
//READ OF FILE EXTENSION (.jpg, .png, .tif, etc...)                            *
//******************************************************************************
       
    /**
     * Retrieves the extention of the userdefined save path.
     * @param FileDestination The path to which the image will be stored
     * @return The extention of the destination file. (ex. jpg, png)
     **/
    static String getExtension(String FileDestination)
    {
        
      String extension;
      
      //READS THE NAME OF THE FILE UNTIL THE FULL STOP
      int dotPos = FileDestination.lastIndexOf(".");
      
      //THE String VARIABLE extension HAS VALUE THE EXTENSION OF THE FILE
      return extension = FileDestination.substring(dotPos+1);

    }
    
//******************************************************************************       
// BufferedImage2Image method                                                  *
//******************************************************************************
    
    /**
     * Receives a BufferedImage as input and returns an Image.
     * @param img The BufferedImage to be converted
     * @return the convertedImage variable that holds the image pixels as Image
     */
    public static Image BufferedImage2Image(BufferedImage img)
    {
        Image convertedImage = null;
         //DEFINES THE COLORMODEL OF THE IMAGE, PIXELBITS, ALPHA, COLORSPACE, COMPONENTS
        ColorModel CM = img.getColorModel();
        //DEFINES THE COLORSPACE OF THE IMAGE
        ColorSpace CS = CM.getColorSpace();
        //READS THE TYPE OF THE COLORSPACE, GREY, RGB, CMYK, LAB
        int Type = CS.getType();
       
        //CONVERTS THE COLORMODEL INFO TO STRING, TO BE PROCESSED
        String colorModel = img.getColorModel().toString();
       
        //SPLITS THE STRING AND SAVES EACH CHUNK TO THE ARRAY stringResult
        String[] stringResult = colorModel.split("\\s");
        
        //DETECTS IF THE IMAGE HAS GREY COLORSPACE
        if("8".equals(stringResult[3]))
        {
           
            
          //  convertedImage = new Image(img.getHeight() , img.getWidth());
          
      
          //WHEN BOTH LOOPS ARE OVER, THE WHOLE IMAGE HAS BEEN PROCESSED AND EACH PIXEL HAS BEEN
          //INSERTED INTO THE NEW IMAGE
          for(int i=0;i<img.getWidth();i++)
            {
                for(int j=0;j<img.getHeight();j++)
                {
                    int RGBColor = img.getRGB(i, j);
                  
                  //  convertedImage.setChannelOfPixel(j, i, 0, RGBColor);
                }
            }
            
        }
        
        //DETECTS IF THE IMAGE HAS RGB COLORSPACE
        else if("24".equals(stringResult[3]))
        {
            int colorArray[] = new int[3];
            int RGBColor;
            
           // convertedImage = new Image( img.getHeight(),img.getWidth(), 3);
            
              for(int i=0;i<img.getWidth();i++)
            {
                for(int j=0;j<img.getHeight();j++)
                {
                    //The discrimination of colors for a pixel
                    RGBColor = img.getRGB(i, j);
                    colorArray[0] = (RGBColor >> 16) & 0xff;
                    colorArray[1] = (RGBColor >> 8) & 0xff;
                    colorArray[2] = (RGBColor) & 0xff;
                    
                    //The colors are inserted into a pixel in the new Image
                //    convertedImage.setPixel(j, i, colorArray[0],colorArray[1],colorArray[2]);
                    
                }
            }
        }
        
        return convertedImage;
    }
    
    // ************************** END OF BufferedImage2Image *******************



     public static void slidingWindow(BufferedImage imageObject , int width , int height , int stepX , int stepY)
        {
            int TOTAL = imageObject.getWidth()*imageObject.getHeight();
            int totalHeight = imageObject.getHeight()-height;
            int totalWidth  =  imageObject.getWidth()-width;

          // featureVector = new ArrayList<ArrayList<int[]>>();
          // featureVector.add(new ArrayList<int[]>());

           int i;
           int j;
           int internalCounter = 0;
           int externalCounter = 0;
           int assosiation = externalCounter;
            for(i = 0; i<=totalHeight; i+=(stepY))
            {

                for(j = 0; j<=totalWidth; j+=(stepX))
                {
                   //int iCounter = i;
                  // int jCounter = j;
                  // imageObject.get(i,j);
                    //this.saveFeatures(this.custom(imageObject.subImage(i, j ,width , height)),false);
                    //makes sure the arrayList has enough space. dynamically increases the arrayList. If you need to change this,
                    // use trimToSize() to make sure it doesn't take any more space than needed.
                   int[] temp = new int[height*width];
                   temp = getVector(i,j,imageObject,height,width);

                   //featureVector.get(assosiation).ensureCapacity(temp.length+1);
                  // featureVector.get(assosiation).add(internalCounter,temp);
                  // featureVector.get(i).add(internalCounter,(double)imageObject.get(i,j));

                   //Array of doubles.
                  //outputArray[i][j] = temp;
                   internalCounter++;
                }
               internalCounter = 0;
               externalCounter++;
               // int sample = makeDouble(featureVector.get(i).get(i),featureVector.get(i).size(),i).length;


               // featureVector.ensureCapacity(i+1);
                //featureVector.add(new ArrayList<int[]>());
            }



         writeOutput(finalString);
         System.out.print(finalString);
          /* This is here for debug, to see if we can retrieve arrays of doubles, from the ArrayList. It works.
           for(int c=0;c<featureVector.get(0).get(0).length;c++)
           {
               double tempValue = (double)featureVector.get(0).get(0)[c];
              // serializer(doubleTemp[c].toString(),false);
                //IJ.log("\n"+"IN >>>>"+tempValue+"::"+c+"--");
           }
           */

        }

  private static int[] getVector(int external, int internal, BufferedImage imp,int height,int width)
    {
        int[] outputArray = new int[width*height];
        int counter = 0;
       // IJ.log(":::"+outputArray.length+"::"+counter+"::"+external+"::"+internal);
        int ext=external;
        int inte=internal;

        for(int i=ext;i<external+height;i++)
        {
            for(int j=inte;j<internal+width;j++)
            {
                outputArray[counter] = imp.getRGB(i, j);
                serializer(Integer.toString(outputArray[counter]),false);
                counter+=1;

            }
            // IJ.log(i+":::"+outputArray.length+"::"+counter+"::");//+sample);

        }
         //new gap
         serializer("0",true);
        //System.gc();
        return outputArray;
    }

   static String finalString = "Feature Vector"+"\n"+"\n";
   static int readabilityCounter = 0;
    /**
     * Performs serialization of the results, appends new feature vectors in rows
     * for better readability when exported to file. Creates a gap between featureVectors.
     * Changes row every 5 entries.
     * @param input The String to be appended
     * @param changeLine whether or not we reached the end of a series of rows.
     */
    public static void serializer(String input,boolean changeLine)
    {
        if(changeLine==true){finalString = finalString+"\n"+"\n";}
        else
        {
            String tempStr = input;
            if(readabilityCounter<6)finalString =  finalString+tempStr+", ";
            else
            {
                finalString = finalString+tempStr+", "+"\n";
                readabilityCounter = 0;
            }
            readabilityCounter++;
        }
    }


    //**************************** End of Image2BufferedImage ******************
    
    
    /**
     * Saves the Image into the disk, runs automated process to distinguish the type of the output 
     * (.jpg, .png, .dcm, .bmp, etc...)
     * @param img The img input is converted to BufferedImage and then it is writen into the disk
     * @param filename The filename of the output file
     */
   public static void save2Disk(Image img, String filename)
	{
        int proceedFlag=0;
         BufferedImage convertedImage = null;
        //THE SUPPORTED FORMATS BY IMAGEIO AND THE EXTENDED JAVA ADVANCED IMAGING (JAI)
        String extensionDictionary[] = {"jpg","png","tif","tiff","bmp","BMP","JPG","PNG","TIF","TIFF","gif","GIF"};
        //THE METHOD THAT DISTINGUISES THE EXTENSION OF THE PROVIDED FILE
        String extensionForLoading = getExtension(filename);
        for(int i=0;i<=11;i++)
        {
            //CHECKS IF THE FILE IS ONE OF THE SUPPORTED FORMATS
            if(extensionForLoading.equals(extensionDictionary[i]))
            {
                proceedFlag = 1;
            }
            
            else if(extensionForLoading.equals("dcm"))
            {
                proceedFlag = 2;
            }
        }
        if(proceedFlag == 1)
        {
            //THE IMAGE IS CONVERTED THROUGH THE Image2BufferedImage METHOD
           // convertedImage = Image2BufferedImage(img);
             try 
            {
                
               //RECEIVES THE EXTENSION OF THE FILE THAT WILL BE WRITEN
               //WRITES THE FILE AS DEFINED BY Filename
               ImageIO.write(convertedImage,getExtension(filename), new File(filename));  
            } 
             catch (Exception e) 
             {
                 e.printStackTrace();
             }
            
        }
        
     /*   else if(proceedFlag == 2)
        {
           //THE IMAGE IS CONVERTED THROUGH THE Image2BufferedImage METHOD
           convertedImage = Image2BufferedImage(img);
            try
             {
                
                DicomIO.bufferedImage2Dicom(convertedImage, filename);
             } 
             catch (IOException e) 
             {
                e.printStackTrace();
             }
        }
      * */
        
	}

    private static void writeOutput(String source)
    {
        try
        {
            BufferedWriter out = new BufferedWriter(new FileWriter("C:/test.txt"));

            //String someText = "aString\nthis is a\nttest";
            //someText.replaceAll("\n", System.getProperty("line.separator"));

            out.write(source);
            out.close();
        }
        catch (IOException e)
        {

        }
    }
   //***************************** End of save *********************************
   
   
   //***************************** ImageJ Compatibility ************************
    public static void main(String[] args) throws Exception
     {
         
         
         // Image picture = new Image(1050, 1890, 1, 256);
          
        IO.load("C:/SDK/TEST.jpg");
      
         // picture.toString();
        
   //       showResults.drawing(IO.Image2BufferedImage(picture) , picture.rows()/2 ,picture.columns()/2);
    	 
     }  
  
} //END OF CLASS
